#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/msg.h>
#include "../md5/md5.c"
#include "../DES/des.c"
#include "MsgType.h"

// Step1 接收消息C和D
void ReceiveFromClient(MsgE *msgE, MsgG *msgG);
// Step2 解密消息E得到K_CS
char* DecryptMsgE(MsgE msgE, char *K_SS);
// Step3 解密消息G
void DecryptMsgG(MsgG msgG, char *K_CS, MsgG *De_msgG);
void CreateMsgH(MsgH *msgH, MsgG De_msgG, char *K_CS);
// Step4 发送消息
void SendToClient(MsgH msgH);

int main()
{
    int i;
    char *K_SS = "service's secret key";
    
    MsgE msgE;
    MsgG msgG;
    MsgG De_msgG;    
    MsgH msgH;
    MsgEInit(&msgE);
    MsgGInit(&msgG);
    MsgGInit(&De_msgG);
    MsgHInit(&msgH);

    msgG.timestamp = "Empty";
    while (1)
    {
        ReceiveFromClient(&msgE, &msgG);
        if (msgG.timestamp != "Empty")
        {
            printf("......\n接收消息E和消息G\n");
            break;
        }
    }
        
    char *K_CS = DecryptMsgE(msgE, K_SS);
    DecryptMsgG(msgG, K_CS, &De_msgG);
    
    CreateMsgH(&msgH, De_msgG, K_CS);
    
    SendToClient(msgH);

    exit(EXIT_SUCCESS);
}

// Step1 接收消息C和D
void ReceiveFromClient(MsgE *msgE, MsgG *msgG)
{
    struct msg_st data;
    long int msgtype = 0;
    //建立消息队列
    int msgid = msgget((key_t)115, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgE->serviceID, data.text);
    
    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgE->clientID, data.text);

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgE->clientAddr, data.text);

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgE->vaildity, data.text);

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgE->K_CS, data.text);

    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    strcpy(msgG->clientID, data.text);


    if (msgrcv(msgid, (void *)&data, BUFSIZ, msgtype, 0) == -1)
    {
        perror("msgcrv failed");
        exit(EXIT_FAILURE);
    }
    msgG->timestamp = (char *)malloc(BUFSIZ*sizeof(char));    
    strcpy(msgG->timestamp, data.text);

    // 删除消息队列
    if (msgctl(msgid, IPC_RMID, 0) == -1)
    {
        perror("msgclt failed");
        exit(EXIT_FAILURE);
    }
}

// Step2 解密消息E得到K_CS
char* DecryptMsgE(MsgE msgE, char *K_SS)
{
    char *K_CS = DecryptionBS(msgE.K_CS, K_SS);
    return K_CS;
}

// Step3 解密消息G
void DecryptMsgG(MsgG msgG, char *K_CS, MsgG *De_msgG){
    De_msgG->clientID = DecryptionBS(msgG.clientID, K_CS);
    De_msgG->timestamp = DecryptionBS(msgG.timestamp, K_CS);
}

void CreateMsgH(MsgH *msgH, MsgG De_msgG, char *K_CS){
    msgH->clientID = EncryptionBS(De_msgG.clientID, K_CS);    
    long timestamp = atoi(De_msgG.timestamp);
    timestamp++;
    char *ts = (char*)malloc(BUFSIZ * sizeof(char));
    sprintf(ts, "%ld", timestamp);
    msgH->ts = EncryptionBS(ts, K_CS);    
}

// Step4 发送消息
void SendToClient(MsgH msgH)
{
    struct msg_st data;
    long int msgtype = 0;
    //建立消息队列
    int msgid = msgget((key_t)116, 0666 | IPC_CREAT);
    if (msgid == -1)
    {
        perror("msgget failed");
        exit(EXIT_FAILURE);
    }

    data.msg_type = 1;
    strcpy(data.text, msgH.clientID);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }

    strcpy(data.text, msgH.ts);
    if(msgsnd(msgid, (void*)&data, BUFSIZ, 0) == -1)  
    {  
        perror("msgsnd failed\n");
        exit(EXIT_FAILURE);  
    }
    printf("......\n发送消息H\n");    
}